ShowTable of Contents
Concept:
You should be able to add controls from the controls palette as well as data from the data palette to the source tab of the XPages editor with the same behavior as adding them to the design tab. You should not be able to generate invalid source.
Supported Methods Of Adding Controls:
There are a number of different ways to add controls to an XPage, all of which are supported in the source editor in the same way that they are supported in the design editor
- Standard drag and drop from the controls palette with the mouse
- Placing the cursor at any location (or selecting a section of code) within the source editor and double clicking a control in the controls palette
- Placing the cursor at any location within the source editor (or selecting a section of code) and using the "Create" menu to insert a control
Supported Methods Of Adding Data:==
- Standard drag and drop from the data palette with the mouse
Drag and Drop behavior for all Controls:
Some basic behavior is the same for all controls regardless of their type. This is when you drop a control to whitespace in the source editor. Whitespace in this context means any blank lines within the xp:view tag and that are not within the opening and closing tags of any other controls.
- If you drop any control to whitespace in the source editor, the control should be created on that line.
- If you select multiple lines of whitespace in the source editor, and use the create menu to add a control (or double click in the controls palette), the control should be dropped to upper most line of whitespace that is selected.
- If you select any section of source code in the source editor which begins with some whitespace (the whitespace can span any number of lines), and use the create menu to add a control (or double click in the controls palette), the control should be dropped to top most line of whitespace that is selected.
Determining the Target Control
If you are not dropping to whitespace, then you must be dropping to another control. Before going into the drop behavior of the various controls, it is important to know what the editor considers your target control to be. The "target control" is the control that you are trying to add another control to. In simple terms, the target control is the control that contains the caret when no source is selected, or the upper most selected control in any source selection. When we deal with selection, we always use the uppermost control in the selection as the target control.
More specifically:
- If you drop to the beginning tag, body or ending tag of a control, that control will be the target control. This is equivalent to placing the caret anywhere inside a controls tag structure.
In this example, you are dropping to an Edit Box control, so that is the target control
In this example the caret is within the tag structure of an Edit Box control, so that is the target control.
- If you select any part of a control in source (so highlight any part of the start tag, body or end tag, or combination of the three, where one or more characters are selected) or select an entire control in source (highlight the entire start tag, body and end tag) that control will be the target control.
In this example, an Edit Box control is partially selected, so that is the target control.
- If you select multiple controls in the source tab (so highlight the entire start tags, body and end tags of multiple controls), the top most selected control will be the target control. This is also true for partial selection of the uppermost control. Even if you only have the very last '>' character of the ending tag of the uppermost control selected, that will be the target control.
In this example, despite the caret location, the uppermost selected control is the Edit Box control, so that will be the target control.
Types of Controls
There are essentially two different types of controls that can be added to an XPage. Those that allow other controls to be added as child controls and those that don't. For example, you cannot drop a button control into an edit box control, but you can drop a button control into a panel control. We refer to controls that do not accept other controls as children as Core Controls, and those to do accept children as Container Controls.
Dragging and Dropping to Core Controls
Core controls have the simplest drop scenarios. They do not allow other controls to be dropped into them. All the controls that reside within the Core Controls drawer of the Controls Palette are considered Core Controls, with the exception of the Link Control. Although the link control is listed as a core control, it can have children, so it is possible to drop into the link control in source. Therefore it is handled in the same way as a container control.
- If your target control is a core control, then the dropped control should be created on the line directly above the target control.
Dragging and Dropping to Container Controls
From here on Container Controls will refer to all the controls in the container control drawer of the controls palette, as well as the Link Control.
Container controls are more complex than core controls. They have two main use cases, where the container control is empty and does not already have child controls, and where the container control does already contain child controls and we are adding more.
Empty Container Controls
- If your target control is an empty container control, the dropped control should be created as a child of the target control.
- If you drop any control to a blank line within the body of a container control, the control will be created on that line.
Non-Empty Container ControlsThe rules for determining the target control for any drop still apply to non-empty container controls, but with some further caveats. This is to try to make it a little easier to add child controls to the top and bottom of a container control
- If you drop any control to the starting tag of a container control, the control will be created as the first child of the target control. So if you were dropping a button to a panel that already contained a checkbox, the button would be added above the checkbox control.
- If you drop any control to the ending tag of a container control, the control will be created as the last child of the target control. So if you were dropping a button to a panel that already contained a checkbox, the button would be added below the checkbox control.
- If you select an entire target control in source (highlight the entire start tag, body and end tag) and use the create menu to insert a control (or double click in the controls palette), the control should be created as the top level child of the container control. So if you were dropping a button to a panel that already contained a checkbox, the button would be added above the checkbox control.
- If you select any part of the closing tag of a container control in source and use the create menu to add a control (or double click in the controls palette), the control will be added as the last child of the target control. So if you were dropping a button to a panel that already contained a checkbox, the button would be added below the checkbox control.
- If you select any part of the starting tag of a container control in source and use the create menu to add a control (or double click in the controls palette), the control will be added as the first child of the target control. So if you were dropping a button to a panel that already contained a checkbox, the button would be added above the checkbox control.
- If you select any part of the starting tag of a container control in source as well as any part of the body of the control and use the create menu to add a control (or double click in the controls palette), the control will be added as the first child of the target control. So if you were dropping a button to a panel that already contained a checkbox, the button would be added above the checkbox control.
Custom Container Control Behavior
Some of the container controls have custom behavior, described here.
Table Control
When you drop a table to the source editor it will create a structure similar to this
where the xp:tr tags represent rows and xp:td tags represent cells. You can only drop into cells in a table. Rows cannot accept children that are not tags and do not accept drop commands. So for the drop to source behavior, you cannot drop children to the table tag or the table row tags, so they act as core controls, but you can drop to the table cell tag, so it acts as a container control.
The selection rules from above hold true and work like this.
- If you try to drop to the xp:td tag using any of the container control conditions from above, the control will be added as a child of the xp:td tag as expected.
- If you try to drop to the xp:tr tag, it does no accept a drop, so we move up and check the table tag. It too won't accept drop, so we move up, in this case to the view tag (could be any container control parent, like a panel as well) which can accept a drop, so the control will be dropped directly above the table tag.
- If you try to drop on the xp:table tag, the control will be dropped directly above the table control.
View Control
When you drop a view panel you should get a structure similar to this
You cannot drop into a viewPanel, or a viewColumn or a viewColumnHeader. So the entire view panel will act as nested Core Controls. So for example if you tried to drop a control onto the viewColumnHeader tag, it would not accept the drop, so we would try to drop to the viewColumn. It wouldn't accept drop either so we would try dropping to the viewPanel, which wouldn't accept the drop, so the control would be dropped just above the starting viewPanel tag.
Data Table
When you drop a data table to a page and add a column to it. (This can only be done in the design editor) you get a structure like this.
So for a simple dataTable, like the one above, the xp:column tag acts as a container control. So you can drag and drop to in all the ways you would expect to be able to drop to a container control. The dataTable tag does no allow drop actions, so it will act as a core control. So if you try to drop to the dataTable tag, it will drop the control above the dataTable.
It gets more complicated when you have to deal with dataTable column headers and footers. The header and footer areas of a dataTable column are not their own tags. There are hidden facets specified for the xp:column tag, So to add a control to the header, you need to wrap the the control in a this.facets tag and then add that as a child of the xp:column tag specifying an xp:key attribute on the control to match the facetName of the hidden facet. So for example, here is a rough example of a dataTable with a span in its header and a button in its footer.
Dropping to the facets tag first of all, will drop up. It will not accept a drop itself, so it will look to its parent, the column, which does accept drop so the control will be added right above the facets tag, inside the column tag.
Dropping to the column tag will never generate the this.facets tag, and will never add a control to the header or footer. You would have to set up the controls in the header and footer either manually in source, or through the Design editor.
But once the header and footer children are created, they act as you would expect. So in this case, we have a span for the header. The span control is a container control, so a user could drag and drop new controls into the span tag using all the same rules as earlier in this document.
We have a button in the footer though, which is a Core Control and does not accept drop actions. So if you try to drop onto the button, it will search up, try to drop on the facets tag, which it can't, search up again, will find that it can drop to the column tag, so will drop the control right above the facets tag, inside the column tag.
Tabbed Panel
The tabbed panel is a special case. It is quite a simple control really. It has a structure like this
The tabPanel tags are container controls and act exactly as you would expect them to given the rules above.
You cannot drop inside a tabbedPanel tag, so for the most part it acts as a Core Control. So if you were to try to drop to its start tag, it would drop the control above the tabbedPanel etc.. as you would expect.
However the tabbed panel has custom drop behavior if you try to drop to its closing tag. Instead of dropping out of the tabbedPanel control and putting the new control above the xp:tabbedPanel tag, it will add the control as the last child of the last tabPanel child of the tabbedPanel control.
So for example if you were to try to drop a button on the closing tag
This behavior is allowed for this control only, because of the restricted nature of the tabbed panel tag structure.
Dragging and Dropping to Custom Controls
Custom controls are a special case as you cannot drop into a custom control by default. You can only drop into a custom control if it has a facet specified (an editable area control added to it). And there are two different types of factes, those that have a facetName and those that don't. If a custom control has a facet with a facetName, that facet can contain one child control only. If the facet does not have a facet name, it can contain any number of child controls. Any custom control can have any number of both types of facets.
Custom controls with a facet could also then have another custom control added to it that has a facet, giving nested facets.
A custom control, may contain another custom control which contains a facet, in which case we have a facet nested to 2 levels. You cannot drop to facets nested to 2 levels.
By default if you were to drop to a custom control it would have acted like a Core Control regardless of any facets and you would have not been able to drop into it.
However, seeing as custom controls and facets are so widely used, we have implemented some support for this.
Take the example a custom control (cc1) on an XPage.
If the drop is allowed into a facet in the custom control, the control is always appended as the last child of the custom control. Even if you drop on the start tag, the new control will always be added as the last child.
As mentioned before, a custom control can have different types of facets, and we have no way of knowing which one was the intended drop target. So an order of preference is used to select a facet to drop to.
- If the custom control has only one valid facet, then use that one, regardless of its type.
- If the custom control has both facets with facetNames and without, we use the facet without the facetName as the target.
- If the custom control has no valid facets to drop to, we don't allow drop, and the control will be added above the custom control tag.
- If the target control has multiple facets with facetNames, the drop action will target the first one that is found that can be dropped to. So for example if you had a custom control that contained 3 Editable Areas with facetNames "facet_1, facet_2, facet_3" (in that order in the custom control), the first drop would drop to facet_1, the next drop we would drop to facet_2 .... and so on. Once all three facets have been filled, any further controls dropped to the custom control will be dropped out and placed above the custom control.
Dragging and Dropping from the Data Palette
You can drag and drop view and document data from the data palette into the source of an XPage. It should have all the same capabilities as dropping into the design editor.
- Dragging and dropping a domino view data source to whitespace in the source editor should drop the selected data elements in the data palette to the selected line in the source editor (drop a view containing view columns bound to the selected data sources in the data palette)
- Dragging and dropping a domino view data source to a control that accepts data (an editBox for example) should set the data binding on that element to be the dropped data source.
- Dragging and dropping a domino view data source to a control that accepts data (an editBox for example) and that already has a data binding set on it (document or view), should reset the data on that control to be the newly dropped data source
- Dragging and dropping a domino view data source onto a control that does not allow data to be set on it, should drop the selected data sources in the data palette directly above the target control in the source editor.
- Dragging and dropping a domino document data source to whitespace in the source editor should drop the selected data elements in the data palette to the selected line in the source editor (drops a table containing an inputText control bound to the data source and with a convertor to set the data type of the inputText... exactly as it would do dropping to the design editor).
- Dragging and dropping a domino document data source to a control that accepts data (an editBox for example) should set the data binding on that element to be the dropped data source.
- Dragging and dropping a domino document data source to a control that accepts data (an editBox for example) and that already has a data binding set on it (document or view), should reset the data binding on that control to be the newly dropped data source
- Dragging and dropping a domino document data source onto a control that does not allow data to be set on it, should drop the selected data source in the data palette directly above the target control in the source editor.
|